/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.common.base.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.je.common.auth.impl.RealOrganizationUser;
import com.je.common.base.DynaBean;
import com.je.common.base.cache.office.OfficeParamCacheManager;
import com.je.common.base.document.InternalFileBO;
import com.je.common.base.document.InternalFileUpload;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.mvc.AbstractPlatformController;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.office.service.JeOfficeService;
import com.je.common.base.office.vo.JeOfficeVo;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.service.MetaResourceService;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.util.*;
import org.apache.servicecomb.foundation.common.part.ResourcePart;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * office业务类
 */
@RestController
@RequestMapping(value = "/je/office/jeOffice")
public class JeOfficeController extends AbstractPlatformController {
    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;
    @Autowired
    private OfficeParamCacheManager officeParamManager;
    @Autowired
    private JeOfficeService jeOfficeService;
    @Autowired
    private MetaResourceService metaResourceService;
    @Autowired
    private Environment environment;

    /**
     * 直接执行预览下载逻辑
     * @param param
     * @param request
     * @return
     */
    @RequestMapping(value = {"/doExecDoc"},method = RequestMethod.GET, produces = "application/json; charset=utf-8")
    public ResponseEntity<Part> doExecDoc(BaseMethodArgument param, HttpServletRequest request) {
        String type = param.getType();//参数类型  cache为缓存参数，其它为正常request
        String code = param.getCode();//文档模版
        //是否转PDF
        Boolean convertPdf=false;
        if("1".equals(request.getParameter("pdf"))){
            convertPdf=true;
        }
        HashMap<String, Object> params = new HashMap<>();
        String dataStr = "";
        //封装参数
        if ("cache".equals(type)) {
            String uuid = request.getParameter("data");
            HashMap<String,String> paramCaches = officeParamManager.getCacheValue(uuid);
            for(String key:paramCaches.keySet()){
                params.put(key,paramCaches.get(key));
            }
            officeParamManager.removeCache(uuid);
        }else if("base64".equals(type)){
            dataStr = request.getParameter("data");
            if (StringUtil.isNotEmpty(dataStr)) {
                dataStr = Base64.decodeStr(dataStr);
                JSONObject baseParams = JSONObject.parseObject(dataStr);
                for (String key : baseParams.keySet()) {
                    params.put(key, baseParams.getString(key));
                }
            }
        }
        Map<String, String[]> paramInfos = request.getParameterMap();
        for (String key : paramInfos.keySet()) {
            params.put(key, request.getParameter(key));
        }
        if("1".equals(params.get("pdf")+"")){
            convertPdf=true;
        }
        String returnType="exp";
        if(params.containsKey("returnType") && StringUtil.isNotEmpty(params.get("returnType"))){
            returnType=params.get("returnType")+"";
        }
        JeOfficeVo jeOfficeVo=jeOfficeService.doExecDoc(code,params,convertPdf);
        RealOrganizationUser currentUser= SecurityUserHolder.getCurrentAccount().getRealUser();
        String fileSuffix=jeOfficeVo.getFileSuffix();
        String fileName=jeOfficeVo.getName()+"_"+ DateUtils.formatDate(new Date(),"yyyyMMdd")+"."+fileSuffix;
        if(StringUtil.isNotEmpty(jeOfficeVo.getFileName())){
            fileName=jeOfficeVo.getFileName();
        }

        //执行文档返回
        if("exp".equals(returnType)){
//            String defaultDirectory = environment.getProperty("servicecomb.downloads.directory");
//            String filePath=defaultDirectory + File.separator + fileName;
//            FileUtil.writeFromStream(jeOfficeVo.getInputStream(), filePath);
            ResponseEntity.BodyBuilder bodyBuilder = ResponseEntity.ok();
            try {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                fileName = "未知文件."+jeOfficeVo.getFileSuffix();
            }
            bodyBuilder.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
            if(convertPdf) {
                fileName=fileName.substring(fileName.lastIndexOf("."))+".pdf";
                ResourcePart resourcePart = new ResourcePart(fileName, new InputStreamResource(jeOfficeVo.getPreviewStream()));
                resourcePart.contentType(jeOfficeVo.getPreviewContextType());
                return bodyBuilder.body(resourcePart);
            }else{
                ResourcePart resourcePart = new ResourcePart(fileName, new InputStreamResource(jeOfficeVo.getInputStream()));
                resourcePart.contentType(jeOfficeVo.getFileContextType());
                return bodyBuilder.body(resourcePart);
            }
        }else if("preview".equals(returnType)){
            fileName=fileName.substring(fileName.lastIndexOf("."))+".pdf";
            try {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                fileName = "未知文件.pdf";
            }
            ResponseEntity.BodyBuilder bodyBuilder = ResponseEntity.ok();
            bodyBuilder.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
            ResourcePart resourcePart=new ResourcePart(fileName,new InputStreamResource(jeOfficeVo.getPreviewStream()));
            resourcePart.contentType(jeOfficeVo.getPreviewContextType());
            return bodyBuilder.body(resourcePart);
        }
        else{
            throw new PlatformException("该文档只支持下载，如果保存则调用doExecExpDoc接口!", PlatformExceptionEnum.JE_CORE_PARAMPW_ERROR);
        }
    }

    /**
     * 执行业务逻辑保存逻辑
     * @param param
     * @param request
     * @return
     */
    @RequestMapping(value = {"/doExecDataDoc"},method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doExecDataDoc(BaseMethodArgument param, HttpServletRequest request){
        String type = param.getType();//参数类型  cache为缓存参数，其它为正常request
        String code = param.getCode();//文档模版
        //是否转PDF
        Boolean convertPdf=false;
        if("1".equals(request.getParameter("pdf"))){
            convertPdf=true;
        }
        HashMap<String, Object> params = new HashMap<>();
        String dataStr = "";
        //封装参数
        if ("cache".equals(type)) {
            String uuid = request.getParameter("data");
            HashMap<String,String> paramCaches = officeParamManager.getCacheValue(uuid);
            for(String key:paramCaches.keySet()){
                params.put(key,paramCaches.get(key));
            }
            officeParamManager.removeCache(uuid);
        }else if("base64".equals(type)){
            dataStr = request.getParameter("data");
            if (StringUtil.isNotEmpty(dataStr)) {
                dataStr = Base64.decodeStr(dataStr);
                JSONObject baseParams = JSONObject.parseObject(dataStr);
                for (String key : baseParams.keySet()) {
                    params.put(key, baseParams.getString(key));
                }
            }
        } else {
            Map<String, String[]> paramInfos = request.getParameterMap();
            for (String key : paramInfos.keySet()) {
                params.put(key, request.getParameter(key));
            }
        }
        if("1".equals(params.get("pdf")+"")){
            convertPdf=true;
        }
        String returnType="file";
        if(params.containsKey("returnType") && StringUtil.isNotEmpty(params.get("returnType"))){
            returnType=params.get("returnType")+"";
        }
        JeOfficeVo jeOfficeVo=jeOfficeService.doExecDoc(code,params,convertPdf);
        RealOrganizationUser currentUser= SecurityUserHolder.getCurrentAccount().getRealUser();
        String fileSuffix=jeOfficeVo.getFileSuffix();
        String fileName=jeOfficeVo.getName()+"_"+ DateUtils.formatDate(new Date(),"yyyyMMdd")+"."+fileSuffix;
        if(StringUtil.isNotEmpty(jeOfficeVo.getFileName())){
            fileName=jeOfficeVo.getFileName();
        }
        if("file".equals(returnType)) {
            InternalFileUpload uploadFile = new InternalFileUpload(fileName, jeOfficeVo.getFileContextType(), jeOfficeVo.getFileSize());
            String tempDir = this.environment.getProperty("servicecomb.downloads.directory");
            String tempFilePath = tempDir + "/" + JEUUID.uuid() + "." + jeOfficeVo.getFileSuffix();
            FileUtil.writeFromStream(jeOfficeVo.getInputStream(), tempFilePath);
            File file = new File(tempFilePath);
            JSONObject metadata=new JSONObject();
            InternalFileBO fileBO = documentInternalRpcService.saveSingleFileWithMetadata(uploadFile, file, currentUser.getId(),metadata);
            return BaseRespResult.successResult(jeOfficeService.transformVO(fileBO));
        }else if("filesave".equals(returnType)){
            String tableCode=params.get("tableCode")+"";//param.getTableCode();
            String pkValue=params.get("pkValue")+"";//param.getPkValue();
            String fieldCode=params.get("fieldCode")+"";//param.getParameter("fieldCode");
//            String previewFieldCode=param.getParameter("previewFieldCode");
            DynaBean bean=null;
            if(StringUtil.isNotEmpty(tableCode) && StringUtil.isNotEmpty(pkValue)) {
                bean=metaService.selectOneByPk(tableCode, pkValue);
            }
            if(bean!=null) {
                if(StringUtil.isNotEmpty(fieldCode)) {
                    InternalFileUpload uploadFile = new InternalFileUpload(fileName, jeOfficeVo.getFileContextType(), jeOfficeVo.getFileSize());
                    String tempDir = this.environment.getProperty("servicecomb.downloads.directory");
                    String tempFilePath = tempDir + "/" + JEUUID.uuid() + "." + jeOfficeVo.getFileSuffix();
                    FileUtil.writeFromStream(jeOfficeVo.getInputStream(), tempFilePath);
                    File file = new File(tempFilePath);
                    JSONObject metadata=new JSONObject();
                    InternalFileBO fileBO = documentInternalRpcService.saveSingleFileWithMetadata(uploadFile, file, currentUser.getId(),metadata);
                    JSONArray fileVals=new JSONArray();
                    JSONObject fileObj=new JSONObject();
                    fileObj.put("relName",fileBO.getRelName());
                    fileObj.put("fileKey",fileBO.getFileKey());
                    fileObj.put("suffix",fileBO.getSuffix());
                    fileObj.put("size",fileBO.getSize());
                    fileVals.add(fileObj);
                    bean.set(fieldCode,fileVals.toString());
                }
//                if(StringUtil.isNotEmpty(previewFieldCode)){
//                    fileName=fileName.substring(fileName.lastIndexOf("."))+".pdf";
//                    InternalFileUpload uploadFile = new InternalFileUpload(fileName, jeOfficeVo.getPreviewContextType(), jeOfficeVo.getPreviewFileSize());
//                    String tempDir = this.environment.getProperty("servicecomb.downloads.directory");
//                    String tempFilePath = tempDir + "/" + JEUUID.uuid() + "." + jeOfficeVo.getPreviewSuffix();
//                    FileUtil.writeFromStream(jeOfficeVo.getInputStream(), tempFilePath);
//                    File file = new File(tempFilePath);
//                    InternalFileBO fileBO = documentInternalRpcService.saveSingleFile(uploadFile, file, currentUser.getId());
//                    bean.set(previewFieldCode,fileBO.getRelName()+"*"+fileBO.getFileKey());
//                }
                bean=metaService.updateAndReturn(bean);
                return BaseRespResult.successResult(bean);
            }else{
                return BaseRespResult.errorResult("未找到业务表数据!");
            }
        }else{
            return BaseRespResult.errorResult("未识别的返回类型["+returnType+"]");
        }
    }
    @RequestMapping(value = "/doCacheParam", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doCacheParam(BaseMethodArgument param, HttpServletRequest request) {
        HashMap<String, String> params = new HashMap<>();
        Map<String, String[]> paramInfos = request.getParameterMap();
        for (String key : paramInfos.keySet()) {
            if("j_query".equals(key)){
                params.put("j_query",param.getjQuery());
            }else {
                params.put(key, request.getParameter(key));
            }
        }
        String uuid = JEUUID.uuid();
        officeParamManager.putCache(uuid, params);
        return BaseRespResult.successResult(uuid);
    }


}
